﻿using System;
using System.Linq.Expressions;

using Tszy.Unlimited.Base.Collections;

namespace Tszy.Unlimited.Data.AdoNet.Sql.Components.Visitors
{
    /// <summary>
    ///
    /// </summary>
    public interface IExpressionCache
    {
        /// <summary>
        ///
        /// </summary>
        /// <param name="key"></param>
        /// <param name="expression"></param>
        /// <param name="func"></param>
        /// <returns></returns>
        Delegate Get(string key, Expression expression, Func<Expression, Delegate> func);
    }

    /// <summary>
    ///
    /// </summary>
    public class HashedListCache : IExpressionCache
    {
        private static readonly object _lockObject = new();
        private static readonly MonoConcurrentDictionary<string, Delegate> _delegates = new();

        /// <summary>
        ///
        /// </summary>
        /// <param name="key"></param>
        /// <param name="expression"></param>
        /// <param name="func"></param>
        /// <returns></returns>
        public Delegate Get(string key, Expression expression, Func<Expression, Delegate> func)
        {
            if (expression == null)
                throw new ArgumentNullException(nameof(expression));

            key += expression.ToString();

            if (!_delegates.ContainsKey(key))
            {
                lock (_lockObject)
                {
                    if (!_delegates.ContainsKey(key))
                    {
                        _delegates[key] = func(expression);
                    }
                }
            }

            return _delegates[key];
        }
    }
}